Dynamische Netzwerke in R

Eine Einführung

Björn Siepe

AE Psychologische Methodenlehre, Philipps-Universität Marburg

2023-06-23

Allgemeine Informationen

Materialien

https://bit.ly/netz-work-material

Ziele

  1. Refresher zu Netzwerken
  2. Überblick über relevante Packages
  3. Datenvorverarbeitung
  4. Einführung in graphicalVAR
  5. FAQ zu graphicalVAR
  6. Einführung in GIMME
  7. FAQ zu GIMME
  8. GIMME Beispiel
  9. Ausblick

Was wir auslassen

  1. graphicalVAR im Detail
  2. Coden mit anderen Packages
  3. Viele statistische Details
  4. Einführung in R
  5. Latente Variablen (LV-GIMME, DSEM)
  6. Confirmatory GIMME

Refresher: Netzwerke

Netzwerktheorie:

  • kausale Interaktion von Symptomen anstatt Syndrome
  • keine monokausale Erklärung
  • verschiedene Zustände des komplexen Systems (gesund vs. krank)
  • stark verbundene Symptome verstärken sich gegenseitig

Refresher: Netzwerke

  • Netzwerke bestehen aus Knoten (nodes) und Kanten (edges)
  • Knoten:
    • Personen, Städte, Maschinenteile, Symptome
  • Kanten:
    • gewichtet/ungewichtet
    • direktional/undirektional

Refresher: Längsschnittliche Netzwerke

Refresher: Längsschnittliche Netzwerke

  • Ziel: Dynamische Zusammenhänge von Variablen auf individueller Ebene betrachten
  • Oftmals Analyse von zwei Ebenen:
    • temporal: Über Zeitpunkte hinweg
    • contemporaneous: Während eines Zeitpunktes

Relevante Packages

  • graphicalVAR: idiographische Netzwerke
  • mlVAR: Multilevel, ermöglicht Visualisierung von Heterogenität
  • GIMME: idionomisch
  • mgm: Mixed models & zeitlich variierend
  • DSEM (MPlus): komplexe Messmodelle, sehr flexibel
  • BGGM. Bayesianische Methoden
  • psychonetrics: übergreifende Architektur
  • dynr: Dynamische Systeme

Vorbereitung

  • generell: gerade bei der Datenvorbereitung gibt es teilweise etwas komplexeren Code
  • kein Problem, wenn dieser nicht verstanden wird! Bei Nachfragen: E-Mail an mich
  • gibt zusätzliches R-File, in dem alles enthalten ist
  • R Notation: ::: fragment
data |> 
  t.test()   
# äquivalent zu
t.test(data)
dplyr::select()
packagename::funktionsname()

:::

Materialien für heute

Hintergrund:

  • 100 Tage Tagebuchdaten zu Affekt, zwischenmenschlichem Verhalten, Stress, und Functioning
  • Alle PB: Diagnose mindestens einer Persönlichkeitsstörung
  • 94 Personen

für Modellfitting: erste 30 IDs

Vorverarbeitung von Daten

Sehr wichtiger Schritt

Einfluss von Datenvorverarbeitung auf Ergebnisse wird oftmals unterschätzt!

  1. Datenformat
  2. Fehlende Daten
  3. Zeittrends
  4. Verteilungen & Variabilität

Datenformat

Abhängig vom Package

  • graphicalVAR: Dataframe im Long-Format (jede Beobachtung eine Zeile)
  • GIMME: Listenformat oder individuelle Datenfiles in einem Ordner
  • wichtig: Beobachtungen in die richtige zeitliche Reihenfolge bringen!
  • unterschiedliche Zahl von Beobachtungen möglich

Fehlende Daten

Abhängig vom Package:

  • graphicalVAR: Akzeptiert keine fehlenden Daten. Imputation vorab, etwa univariat über Kalman-Filter aus (na_kalman aus tsImpute)
data$var1_imp <- imputeTS::na_kalman(data$var1)
  • GIMME: Geht selbst mit fehlenden Daten um (Full Information Maximum Likelihood)
  • Nicht nur absoluten Wert an fehlenden Daten betrachten, sondern auch Länge des Intervalls, in dem Daten fehlen (fehlt etwa eine ganze Woche vs. fehlt immer mal wieder ein einzelner Wert)

Detrending

  • Verletzung der Stationaritätsannahme (s. Workshop 1) führt zu verzerrten Ergebnissen
  • Detrending bereinigt Zeittrends
  • Trend entfernen bedeutet Information entfernen!
  • Oftmals: entfernen eines linearen Zeittrends
  • Funktion dafür im Code-Appendix
data$var1_detrend <- fn_detrend(data$var1)
  • heißt nicht, dass damit alle Probleme gelöst sind! (kann komplexere Trends geben)

Detrending

Zeitintervalle

Hoch relevant für die Interpretation!

Mehrere Möglichkeiten:

  1. Explizite Modellierung über continuous-time Modellierung (ctsem)

  2. Auslassen von Effekten über die Nacht in graphicalVAR oder GIMME

  3. Cubic Spline Interpolation (s. Fisher et al., 2017)

  4. Ignorieren 😓

Verteilungsannahmen

  • graphicalVARund GIMME: Normalverteilte Variablen
  • sehr oft(!) verletzt: Floor effects, Schiefe, Multimodalität
  • Was passiert? Wir wissen es nicht genau
  • Effekte werden verschätzt

Allgemeine Tips

  • nicht zu schnell mit der Modellierung beginnen
  • viele deskriptive Statistiken
    • auf Individualebene!
  • Plotten, plotten, plotten!
    • etwa: Histogramme von allen Variablen für alle Teilnehmenden
    • oder: alle Zeitreihen einmal plotten lassen
  • Mehr Infos: Siepe et al. (in prep, s. Kursmaterialien)

graphicalVAR

Einführung in graphicalVAR

  • graphicalVAR (Espkamp, 2018) ermöglicht idiographische Netzwerkanalysen
  • Theorie: Erklärt im 1. Workshop (Slides)
  • Schätzt temporales und contemporaneous Netzwerk
  • rein idiographisch, aber: gibt Clustering-Ansatz (Park et al., 2022)

Einführung in graphicalVAR

  • nimmt gleiche Zeitabstände an
  • LASSO-Regularisierung führt zu sparsamen Netzwerken
  • in kurzen Zeitreihen: geringe Power führt zu unsicheren Ergebnissen & geringer Konnektivität

Interpretation von Heterogenität

Netzwerke sehen durch Schätzunsicherheit oft heterogener aus, als sie tatsächlich sind (Hoekstra et al., 2022; Siepe et al., in prep.)

graphicalVAR in Code

fit <- graphicalVAR(
  data = NULL,        # Datensatz
  nLambda = 50,       # Anzahl von LASSO Parametern, die getestet wird
  gamma = 0.5,        # EBIC Hyperparameter
  scale = TRUE,       # z-standardisieren (wichtig für LASSO!)
  vars = NULL,        # Vektor mit Variablennamen
  beepvar = "beep",   # Beepvariable
  dayvar = "day",     # Tagesvariable
  idvar = "id"        # ID der Person
  
)

grahpicalVAR Ergebnisse

graphicalVAR Unsicherheit

  • Wichtig: Nicht nur Punktschätzer betrachten!
  • Bootstrapping, um Stabilität der Ergebnisse zu beachten
  • etwa mit boot oder dem bootnet-Package

graphicalVAR-FAQ

Vorab gestellte Fragen:

  1. Wichtigkeit von nLambda?

  2. Umgang mit EBIC Hyperparameter \(\gamma\)

  3. Einfluss von Detrending

  4. Lags bei graphicalVAR

graphicalVAR-FAQ

  1. Wichtigkeit von nLambda?

A: Anzahl unterschiedlicher LASSO Regularisierungsparameter. Typischerweise wird default von 50 verwendet

  1. EBIC Hyperparameter \(\gamma\)

A: Wird gerade bei wenigen Daten oftmals auf 0 gesetzt (s. Mansueto et al, 2022). Dann wird EBIC zum normalen BIC. Abhängig vom Ziel der Untersuchung (Spezifizität vs. Sensitivität).

graphicalVAR-FAQ

  1. Was passiert ohne Detrending?

A: Scheinzusammenhänge zwischen Variablen, die eigentlich nicht miteinander zusammenhängen

  1. Umgang mit Nachteffekten in graphicalVAR

A: Bei Spezifikation von Beep-Variable wird der Effekt vom letzten Beep eines Tages auf den nächsten nicht geschätzt

GIMME: Theorie

Einführung in GIMME

  • Group Iterative Multiple Model Estimation
  • ursprünglich für fMRT-Daten entwickelt
  • personen-spezifische Netzwerke mit dynamischen Zusammenhängen
  • Nutzt Informationen auf Individual-, Subgruppen- & Gruppenebene

Einführung in GIMME

Einführung in GIMME: Technische Infos

  • alternativ auch “structural VAR”
  • lag-1 (Beltz et al., 2016) Zusammenhänge
  • im Prinzip sehr datengetriebene Strukturgleichungsmodellierung

Vergleich mit graphicalVAR

  • graphicalVAR: rein idiographisch (kann aber auf Multilevel erweitert werden)
  • graphicalVAR: Schätzt erst temporal, dann contemporaneous
  • Contemporaneous Effekte:
    • GIMME: gerichtet zwischen beobachteten Variablen
    • graphicalVAR: ungerichtet zwischen Residuen
  • hybrid-GIMME (Luo et al., 2023): Verbindet beides! Braucht aber auch mehr Daten

Zusatzinformation

Die zugrundeliegenden Modelle können mathematisch ineinander transformiert werden (Luo et al., 2023)

GIMME: Algorithmus

Gates et al. (2017)

GIMME: Modellschätzung theoretisch

Takeaway-Zusammenfassung:

  1. Ein “leeres” Modell für temporal und contemporaneous Zusammenhänge wird auf die Daten angepasst

  2. Gruppe: Iterative Suche nach Verbindungen (anhand von Modifikationsindizes), die Modellfit für bestimmten Teil (etwa 75%) des Samples signifikant (nach Korrektur \(\alpha = 0.05/n\)) verbessern

  3. Pruning von nicht länger signifikanten Pfaden

  4. Subgruppe: Ähnlichkeiten zwischen Individuen werden gesucht anhand Größe der geschätzten Effekte, daraus wird eine sog. Adjacency Matrix kreiert

  5. Walktrap-Algorithmus, um “communities” zu identifizieren

  6. In den entstandenen Subgruppen: Suche nach verbessernden Pfaden für bestimmten Teil (etwa 51%) der Subgruppe (nach Korrektur \(\alpha = 0.05/n\))

  7. Pruning von nicht länger signifikanten Pfaden

  8. Individuell: Suche nach verbessernden Pfaden (\(\alpha = 0.01\)), bis “exzellenter Fit” erreicht ist (RMSEA < .05, SRMR < .05, CFI > .95, NNFI > .95).

GIMME: Modellschätzung formell

\[ \eta_{i,t} = (\color{Red}{A_i} + \color{Blue}{A^S_{i,k}} + \color{orange}{A^g_i})\eta_{i,t} + (\color{Red}{\phi_i} + \color{Blue}{\phi^s_{i,k}} + \color{orange}{\phi^g_i})\eta_{i,t-1} + \zeta_{i,t} \]

\(\eta_{i,t}\): Daten von Individuum \(i\) zum Zeitpunkt \(t\)

\(A\): Contemporaneous Effekte

\(\phi\): Temporale Effekte (VAR-1 Modell)

Orange: Gruppeneffekte

Blau: Subgruppeneffekte

Rot: Individuelle Effekte

\(\zeta_{i,t}\): Residuum von Individuum \(i\) zum Zeitpunkt \(t\)

Verschnaufpause

GIMME: Modellfunktion in R

fit <- gimmeSEM(
  data = NULL,         # Datenfile
  out = NULL,          # Outputordner
  ar = TRUE,           # Autoregressive Effekt schätzen (default)
  plot = TRUE,         # Plotten?
  subgroup = TRUE,     # Subgruppen schätzen?
  hybrid = FALSE,      # directed & undirected contemporaneous
  groupcutoff = .75,   # Gruppencutoff
  subcutoff = .51,     # Subgruppencutoff
  ...
)

GIMME: Simulationsergebnisse

  • insgesamt eher konservativ, gerade auf individueller Ebene (Lane et al., 2019)
    • Absenz von Pfaden vorsichtig interpretieren
  • Anzahl Zeitpunkte & Variablen: Hängt von gewünschter Betrachtungsebene ab
    • gerade für individuelle Effekte: \(t > 100\) empfohlen (nur ein sehr grober Richtwert)
  • stärkere temporale Effekte machen Modellschätzung & Subgruppenfindung leichter
    • vorsichtig bei Vergleich mit fMRT-Studien: dort deutlich andere Datenlage
  • gerichtete contemporaneous Effekte: sehr schwer bei \(t < 100\)
  • vermutlich zwischen 5-10 Variablen am besten

GIMME: FAQ

Vorab gestellte Fragen:

  1. Stationarität bei GIMME
  2. Wie werden gerichtete Effekte im contemporaneous Netzwerk geschätzt? Wie reliabel sind diese?

GIMME FAQ: Stationarität

  • Typischerweise: Detrending von linearem Zeittrend
  • Außerdem: Einfügen von NA für die Nacht, damit der Nachteffekt nicht geschätzt wird

Effektive Stichprobengröße

Bei Weglassen von Nachteffekten verringert sich die effektive Stichprobengröße!

GIMME FAQ: contemporaneous Effekte

  • Kontrolle von Autokorrelation in Variablen ermöglicht gerichtete Effekte
  • Wie gut werden diese geschätzt? Hängt sehr von Stärke des Effekts ab
  • Korrekte Richtung des Effekts erst ab \(t > 200\) zufriedenstellend
  • Persönliche Meinung: Würde diese nicht zu stark interpretieren

GIMME: Praxis

GIMME: Anwendung 1

Wir treffen die notwendigen Vorbereitungen und laden die relevanten Daten. Diese wurden bereits vorab in das notwendige Listenformat umgewandelt und etwas vorverarbeitet, Code dafür ist vorhanden.

Code für Listenstruktur
file_list <- list.files(here::here("Anwendungs_Workshop/data/individual_files"), 
                        full.names = TRUE)
data_list <- lapply(file_list, read.csv)

# Zeitvariable hinzufügen
data_list <- lapply(data_list, function(x){
  x <- x |> 
    dplyr::mutate(time = dplyr::row_number())
})


saveRDS(data_list, here::here("Anwendungs_Workshop/data/data_list.RDS"))

Jedes Individuum hat einen eigenen Eintrag in einer Liste.

library(gimme)    # Modellierung
library(here)     # replizierbare Datenstruktur

# Einladen der Datenliste
data_list <- readRDS(here::here("Anwendungs_Workshop/data/data_list.RDS"))

# Erstellen der relevanten Ordner
dir.create(here::here("Anwendungs_Workshop/output"))

Datenvorverarbeitung

  • Listenformat der Daten macht Vorverarbeitung komplizierter
  • gibt mehrere Lösungen, etwa mittels for-loop:
# Liste für Output erstellen
mean_dom <- list()

## Iteriere durch die Liste, gebe Mittelwert aus
# Für Person p in 1 bis Länge der Liste 
for(p in 1:length(data_list)){ 
  # Berechne Mittelwert von Dominance, speichere im Element "p"
   mean_dom[[p]] <- mean(data_list[[p]]$Dominance, na.rm = TRUE)
}

Datenvisualisierung

Histogramm für alle Variablen einer Person:

Hmisc::hist.data.frame(data_list[[2]])

Mein Tipp: Ein großes PDF für alle Histogramme für alle Personen!

# starte PDF
pdf("all_histograms.pdf")

# Loope über alle Personen
for(p in 1:length(data_list)){
  Hmisc::hist.data.frame(data_list[[p]])
}

# stoppe PDF
dev.off()

Datendeskription

Für bessere Übersicht: Deskriptive Statistiken aller Variablen:

  • skimr::skim()
  • dplyr::glimpse()
  • Hmisc::describe()

Datendeskription

Beispiel für Individuum 2:

skim_type skim_variable n_missing complete_rate numeric.mean numeric.sd numeric.p0 numeric.p25 numeric.p50 numeric.p75 numeric.p100 numeric.hist
numeric Dominance 3 0.9651163 2.9781928 6.2290361 -9.95 -1.44 2.71 7.95 16.90 ▃▇▇▅▃
numeric Affiliation 2 0.9767442 -1.3853571 6.2989306 -13.90 -5.00 -0.82 2.83 12.66 ▃▅▇▃▂
numeric PosAff 0 1.0000000 3.8459302 1.2070434 1.00 3.40 4.20 5.00 5.00 ▂▂▂▃▇
numeric NegAff 0 1.0000000 1.9906977 0.8584018 1.00 1.40 1.80 2.60 5.00 ▇▃▂▁▁
numeric Stress 0 1.0000000 0.5581395 1.8188856 0.00 0.00 0.00 0.00 9.00 ▇▁▁▁▁
numeric Functioning 0 1.0000000 0.4534884 0.6800861 0.00 0.00 0.00 1.00 2.00 ▇▁▃▁▁
numeric time 0 1.0000000 43.5000000 24.9699820 1.00 22.25 43.50 64.75 86.00 ▇▇▇▇▇

Datenvorverarbeitung: Variabilität

  • betrachten der Standardabweichung
  • Variabilität sollte nicht zu unterschiedlich sein!
  • ggf. standardisieren/durch Konstante teilen
  • in der Praxis: Auch noch floor effects betrachten, um ggf. einzelne Personen auszuschließen

Datenvorverarbeitung: Variabilität

Über alle Personen hinweg:

Code
# relevante Variablen
rel_vars <- c("Dominance", "Affiliation", "PosAff",
              "NegAff", "Stress", "Functioning")

# Berechnen von Mean und SD
desc_list <- list()
for(p in 1:length(data_list)){
  desc_list[[p]] <- data_list[[p]] |> 
    dplyr::summarize(across(all_of(rel_vars),
                     list(mean = mean, sd = sd), na.rm = TRUE))
  
}
df_desc <- bind_rows(desc_list, .id = "id")

df_desc |> 
  dplyr::summarize(across(everything(),
                   ~ round(mean(.), 3))) |> 
  select(-id) |> 
  gt()
Dominance_mean Dominance_sd Affiliation_mean Affiliation_sd PosAff_mean PosAff_sd NegAff_mean NegAff_sd Stress_mean Stress_sd Functioning_mean Functioning_sd
0.491 2.711 1.912 3.333 2.666 0.61 1.786 0.516 2.425 2.391 1.147 0.69

Für einzelne Individuen:

Code
# Diesmal vorher nach Individuum gruppieren
df_desc |> 
  dplyr::group_by(id) |> 
  dplyr::summarize(across(everything(),
                   ~ round(mean(.), 3))) |>
  head(n = 6L) |> 
  gt()
id Dominance_mean Dominance_sd Affiliation_mean Affiliation_sd PosAff_mean PosAff_sd NegAff_mean NegAff_sd Stress_mean Stress_sd Functioning_mean Functioning_sd
1 -6.352 1.928 -5.662 2.896 1.533 0.266 2.355 0.448 2.783 2.417 2.772 0.494
10 2.306 2.367 2.259 2.520 3.006 0.350 1.411 0.379 2.959 2.685 1.371 0.527
11 3.610 1.532 7.122 2.515 3.188 0.390 1.152 0.283 0.337 1.627 0.574 0.517
12 0.625 3.478 0.374 2.907 1.942 0.898 1.625 0.781 1.141 2.832 0.481 0.868
13 0.410 1.270 0.682 1.617 1.557 0.453 1.035 0.116 0.542 1.187 0.115 0.432
14 1.680 3.853 9.364 3.599 3.655 0.848 1.317 0.476 3.065 4.219 0.948 1.134

Datenvorverarbeitung

Visualisierung von fehlenden Daten: etwa mit naniar-Package

visdat::vis_dat(data_list[[6]])

Datenvorverarbeitung

Wir detrenden einen linearen Effekt von Zeit:

# relevante Variablen
rel_vars <- c("Dominance", "Affiliation", "PosAff",
              "NegAff", "Stress", "Functioning")

# Loopen über alle p Participants
for(p in 1:length(data_list)){
    data_list[[p]] <- fn_detrend(data_list[[p]],
               vars = rel_vars, 
               time_var = "time", 
               sig_only = FALSE)
}

# Zeitvariable wieder löschn
for(p in 1:length(data_list)){
  data_list[[p]] <- subset(data_list[[p]], select = -c(time))
}
  • Alternative: Zeit als exogene Variable aufnehmen (s. Woods et al., 2020)

Datenvorverarbeitung: Alternativen

  • lapply für die Arbeit mit Listen
  • in Dataframe arbeiten, dann am Ende in Liste aufsplitten
# lapply statt for loop
mean_list <- lapply(data_list, function(x){
  # x: einzelnes Element von data_list
  mean(x$Dominance, na.rm = TRUE)
  
})

# oder als Datensatz verwenden
df_data <- data_list |> 
  # mit ID abspeichern
  tibble::enframe(name = "ID") |>
  # in dataframe verwandeln
  tidyr::unnest()

# zurück in Liste verwandeln
data_list_new <- split(df_data, df_data$ID)

GIMME: Modellschätzung

GIMME: Modellschätzung

example_data <- gimme::simData
data_list_short <- data_list[1:30]

fit <- gimmeSEM(
  data = data_list_short, 
  out = "Anwendungs_Workshop/output",
  ar = TRUE,           # Autoregressive Effekt schätzen (oftmals empfohlen)
  plot = TRUE,         # Plotten?
  subgroup = TRUE,     # Subgruppen schätzen?
  hybrid = FALSE,      # directed & undirected contemporaneous
  groupcutoff = .75,   # Gruppencutoff
  subcutoff = .51,     # Subgruppencutoff,
  paths = NULL         # vorgegebene Gruppenpfade
)

saveRDS(fit, "Anwendungs_Workshop/output/fit.RDS")

Alternativ: Fertiges Modell laden (s. Codefile)

GIMME: Outputstruktur

  • Hauptordner:
  • Zusammenfassung aller einzelnen Pfade, Fit-Indizes aller Modelle, Counmatrizen, Gruppenplots
  • Subgruppenordner:
  • Countmatrizen, Subgruppenplots
  • Individuelle Ordner:
  • individuelle Pfade, Standardfehler, Individualplots

GIMME: Gruppenergebnis

Datenstruktur anders

Achtung: Datenstruktur ist anders als z.B. in qgraph (Reihe: Outcome, Spalte: Prädiktor)

Hauptoutput: summaryFit.csv

GIMME: Gruppenergebnis

Please specify a file id for individual plots. Otherwise, summary plot is presented.

GIMME: Gruppenergebnis

  • numerische Zusammenfassung
summary_matrix <- read.csv(here("Anwendungs_Workshop/output/summaryPathCountsMatrix.csv"))
summary_matrix 
  Dominancelag Affiliationlag PosAfflag NegAfflag Stresslag Functioninglag
1           30              3         0         1         0              0
2            1             30         1         0         1              0
3            0              1        30         2         0              2
4            1              2         0        30         2              1
5            0              1         1         2        30              0
6            0              0         1         0         1             30
  Dominance Affiliation PosAff NegAff Stress Functioning
1         0           9     13      2      5           2
2         0           0     11      9      4           1
3         8           7      0      0      3           2
4         2           6      5      0      0           1
5         3           2      1     30      0           1
6         2           2      8      3      7           0

GIMME: Subgruppenergebnis

GIMME: Subgruppenergebnis

GIMME: Subgruppenergebnis

  • eventuell besser bei mehr Variablen (Lane et al., 2019)
  • relevant: Stabilität der Subgruppen

Interpretation von Subgruppen

Es kann Subgruppen ohne gemeinsames Edge geben! Ähnlichkeit der Pfade allgemein.

  • möglicherweise interessant: Subgruppen auf verschiedenen Maßen (Mittelwert, Variabilität, Diagnosen…) vergleichen
  • Limitation: keine probabilistiche Zuordnung zu Subgruppen

GIMME: perturbR

  • untersucht Stabilität von Subgruppenlösungen (Gates et al., 2019)
  • Benötigt similarity matrix aus GIMME als Input
library(perturbR)

perturb_gimme <- perturbR(
  sym.matrix = fit$sim_matrix, 
  plot = TRUE, 
  reps = 100,
  errbars = TRUE
)

saveRDS(perturb_gimme, "Anwendungs_Workshop/output/perturb_gimme.RDS")
  • ARI: Adjusted Rand Index. Soll langsam fallen
  • VI: Variation of Information. Soll langsam steigen.

GIMME: perturbR

GIMME: perturbR

GIMME: Subgruppen weiter untersuchen

Mittelwerte und Standardabweichungen von Pfadkoeffizienten betrachten (vgl. Wright et al., 2022):

Code
ind_ests <- read.csv(here("Anwendungs_Workshop/output/indivPathEstimates.csv"))

# kalkulieren Mittelwerte und Standardabweichungen pro Gruppe
ind_ests |> 
  dplyr::group_by(sub_membership, lhs, rhs) |> 
  dplyr::summarize(b_mean = mean(beta, na.rm = TRUE),
            b_sd = sd(beta, na.rm = TRUE)) |> 
  dplyr::ungroup() |> 
  tidyr::pivot_wider(names_from = sub_membership,
                     values_from = c(b_mean, b_sd),
                     names_prefix = "g") |> 
  dplyr::select(1:5) |> 
  head(n = 6L) |> 
  gt()
lhs rhs b_mean_g1 b_mean_g2 b_mean_g3
Affiliation Affiliationlag 0.18437918 0.13801514 0.2105064
Affiliation PosAff 0.24446483 0.50241587 0.3807818
Affiliation PosAfflag 0.27701531 NA NA
Affiliation Stresslag -0.30219626 NA NA
Dominance Affiliation 0.33175084 -0.01683552 NA
Dominance Dominancelag 0.07185154 0.07779693 0.0398697

GIMME: Individuelles Ergebnis

Beispiel Person 2:

plot(fit, file = 2)

GIMME: Individuelles Ergebnis analysieren

  • Hauptoutput: indivPathEstimates.csv

  • Punktschätzer & Standardfehler für alle Edges

Code
indiv_path_estimates <- read.csv(here::here("Anwendungs_Workshop/output/indivPathEstimates.csv"))

indiv_path_estimates |> 
  head(n = 6L) |> 
  gt()
file lhs op rhs beta se z pval level sub_membership
subj1 Dominance ~ Dominancelag 0.16874072 0.10939830 1.5424438 1.229658e-01 group 2
subj1 Affiliation ~ Affiliationlag 0.04503635 0.10034637 0.4488089 6.535695e-01 group 2
subj1 PosAff ~ PosAfflag 0.08918632 0.09241244 0.9650900 3.344997e-01 group 2
subj1 NegAff ~ NegAfflag 0.39274410 0.08865892 4.4298318 9.430659e-06 group 2
subj1 Stress ~ Stresslag -0.16197321 0.08382896 -1.9321869 5.333644e-02 group 2
subj1 Functioning ~ Functioninglag 0.14957882 0.10248307 1.4595466 1.444147e-01 group 2

GIMME: Individuelles Ergebnis

  • Check: Residuen auf zeitliche Korreliertheit überprüfen (Beltz et al., 2016)
    • wenn notwendig: ggf. Lag-2 etc. hinzufügen
  • viele existierende Effekte werden potentiell nicht mit aufgenommen (Lane et al., 2019)
  • eher konservativ

Ausblick

GIMME: Erweiterungen

  • Latente Variablen

  • GIMME mit exogenen Variablen (Beltz & Gates, 2017)

  • etwa: Zeit, Intervention

  • CS-GIMME: Confirmatory Subgroups

  • etwa: wie unterscheiden sich Diagnosegruppen in ihren Dynamiken

GIMME: Multiple Solutions

  • mehrere äquivalente Lösungen
  • Lösung: ms-GIMME, Auswahl mit AIC
  • Kann gerade bei schwachen autoregressiven Effekten sinnvoller sein, als AR-Effekte per Default zu schätzen
fit <- gimme(...,          # rest identisch
      ms_allow = TRUE,     # multiple Lösungen zulassen
      ar = FALSE,          # AR-Effekte nicht sofort schätzen
      ms_tol = 1e-5)       # Default Toleranz für multiple Lösungen

GIMME: Multiple Solutions

Beispieldaten aus dem Package:

ms_fit <- gimme::ms.fit
solution.tree(ms_fit, level =  "group", plot.tree = TRUE)

GIMME: Limitationen

  • gerichtete contemporaneous Effekte mit Vorsicht zu genießen
  • schwer zu treffende/arbiträre Entscheidungen beim Modellieren
  • Fit Indizes, Gruppencutoffs
  • Annahme von gleichen Zeitintervallen
  • autoregressive Effekte freisetzen vs. multiple solutions noch unklar
  • ersteres könnte Homogenität künstlich erhöhen (Beltz & Gates, 2017)
  • primär evaluiert für Präsenz von Edges, weniger für deren Stärke

Zentralitätsmaße

  • noch nicht stark untersucht für Längsschnittnetzwerke
  • eventuell zu trennen für temporal vs. contemporaneous
  • Beispiel etwa Beck & Jackson (2020)

Interessante Anwendungen

  • Zusammenhang von Netzwerkparametern mit transdiagnostischen Fragebögen (Woods et al., 2020)
  • Vorhersage von Therapieverläufen mit Netzwerkparametern:
    • Hehlmann et al. (in prep., siehe Kursmaterialien)
    • Lutz et al. (2018)
  • Centrality etc.
  • Klinische Fallstudien TODO ADD ONG Paper

PREMISE: Klinisches Wissen integrieren

Implementiert in praktischer Online-App

Übung & Literatur

Praktische Aufgaben

  1. Fehlende Daten von Personen 2, 7 und 21 imputieren.
  2. RMSSD berechnen für alle Variablen von Person 2 (TIPP: psych::rmssd).
  3. Für Person 2 ein Netzwerk in graphicalVAR schätzen und mit dem GIMME-Ergebnis vergleichen.
  4. Gruppencutoff für GIMME ändern und Ergebnisse neu inspizieren.

Literatur allgemein

  • Burger, J., Epskamp, S., van der Veen, D. C., Dablander, F., Schoevers, R. A., Fried, E. I., & Riese, H. (2022). A clinical PREMISE for personalized models: Toward a formal integration of case formulations and statistical networks. Journal of psychopathology and clinical science, 131(8), 906–916. https://doi.org/10.1037/abn0000779
  • Fisher, A. J., Reeves, J. W., Lawyer, G., Medaglia, J. D., & Rubel, J. A. (2017). Exploring the idiographic dynamics of mood and anxiety via network analysis. Journal of Abnormal Psychology, 126(8), 1044–1056. https://doi.org/10.1037/abn0000311
  • Haqiqatkhah, M. M., Ryan, O., & Hamaker, E. L. (2022, November 26). Skewness and staging: Does the floor effect induce bias in multilevel AR (1) models?. https://doi.org/10.31234/osf.io/myuvr
  • Lutz, W., Schwartz, B., Hofmann, S.G. et al. Using network analysis for the prediction of treatment dropout in patients with mood and anxiety disorders: A methodological proof-of-concept study. Sci Rep 8, 7819 (2018). https://doi.org/10.1038/s41598-018-25953-0

Literatur allgemein

  • Park, J. J., Chow, S. M., Fisher, Z. F., & Molenaar, P. C. M. (2020). Affect and Personality: Ramifications of Modeling (Non-)Directionality in Dynamic Network Models. European journal of psychological assessment : official organ of the European Association of Psychological Assessment, 36(6), 1009–1023. https://doi.org/10.1027/1015-5759/a000612
  • von Klipstein, L., Servaas, M. N., Lamers, F., Schoevers, R. A., Wardenaar, K. J., & Riese, H. (2023). Increased affective reactivity among depressed individuals can be explained by floor effects: An experience sampling study. Journal of affective disorders, 334, 370–381. https://doi.org/10.1016/j.jad.2023.04.118

Literatur graphicalVAR

  • Hoekstra, R. H. A., Epskamp, S., & Borsboom, D. (2022). Heterogeneity in Individual Network Analysis: Reality or Illusion?. Multivariate behavioral research, 1–25. Advance online publication. https://doi.org/10.1080/00273171.2022.2128020
  • Sacha Epskamp, Lourens J. Waldorp, René Mõttus & Denny Borsboom (2018) The Gaussian Graphical Model in Cross-Sectional and Time-Series Data, Multivariate Behavioral Research, 53:4, 453-480, DOI: 10.1080/00273171.2018.1454823
  • Park, J. J., Chow, S., Epskamp, S., & Molenaar, P. (2022, October 15). Subgrouping with Chain Graphical VAR Models. https://doi.org/10.31234/osf.io/u3ve8
  • Mansueto, A. C., Wiers, R. W., van Weert, J., Schouten, B. C., & Epskamp, S. (2022). Investigating the feasibility of idiographic network models. Psychological methods.

Literatur GIMME

  • Adriene M. Beltz & Peter C. M. Molenaar (2016) Dealing with Multiple Solutions in Structural Vector Autoregressive Models, Multivariate Behavioral Research, 51:2-3, 357-373, DOI: 10.1080/00273171.2016.1151333
  • Beltz, A. M., Wright, A. G., Sprague, B. N., & Molenaar, P. C. (2016). Bridging the nomothetic and idiographic approaches to the analysis of clinical data. Assessment, 23(4), 447-458.
  • Kathleen M. Gates, Stephanie T. Lane, E. Varangis, K. Giovanello & K. Guiskewicz (2017) Unsupervised Classification During Time-Series Model Building, Multivariate Behavioral Research, 52:2, 129-148, DOI: 10.1080/00273171.2016.1256187
  • Gates, K. M., Fisher, Z. F., Arizmendi, C., Henry, T. R., Duffy, K. A., & Mucha, P. J. (2019). Assessing the robustness of cluster solutions obtained from sparse count matrices. Psychological methods, 24(6), 675–689. https://doi.org/10.1037/met0000204

Literatur GIMME

  • Lane, S. T., Gates, K. M., Pike, H. K., Beltz, A. M., & Wright, A. G. (2019). Uncovering general, shared, and unique temporal patterns in ambulatory assessment data. Psychological methods, 24(1), 54.
  • Nestler, S., & Humberg, S. (2021). GIMME’s ability to recover group-level path coefficients and individual-level path coefficients. Methodology, 17(1), 58-91.
  • Wright, A. G. C., Gates, K. M., Arizmendi, C., Lane, S. T., Woods, W. C., & Edershile, E. A. (2019). Focusing personality assessment on the person: Modeling general, shared, and person specific processes in personality and psychopathology. Psychological Assessment, 31(4), 502–515. https://doi.org/10.1037/pas0000617

Anwendungen

  • Beck, E. D., & Jackson, J. J. (2020). Consistency and change in idiographic personality: A longitudinal ESM network study. Journal of personality and social psychology, 118(5), 1080–1100. https://doi.org/10.1037/pspp0000249
  • Woods, W. C., Arizmendi, C., Gates, K. M., Stepp, S. D., Pilkonis, P. A., & Wright, A. G. C. (2020). Personalized models of psychopathology as contextualized dynamic processes: An example from individuals with borderline personality disorder. Journal of consulting and clinical psychology, 88(3), 240–254. https://doi.org/10.1037/ccp0000472

Weitere Ressourcen

  • Open Handbook of ESM (KU Leuven, 2022)
  • Intensive Longitudinal Analysis of Human Processes (Gates & Molenaar, 2023)
  • GIMME Homepage, die teilweise dieses Tutorial inspiriert hat
  • GIMME Workshop, ebenfalls Inspiration für diesen Workshop

Kontakt

Feel

free

to

contact

me

bjoern.siepe@uni-marburg.de